home *** CD-ROM | disk | FTP | other *** search
-
- AROS Coding Style
- -----------------
-
- (C) 1995 AROS - The Amiga Replacement OS
-
- Aaron "Optimizer" Digulla
- digulla@home.lake.de
-
- 0. Preface
- ----------
-
- Since many people work with you, there have to be rules about how to
- code. This file defines all the standards used in AROS with respect
- to style of source code.
-
- 1. Introduction
- ----------------
- 1.1 General AOS Development Guidelines
- --------------------------------------
-
- * The language: Write it in ANSI C: Use full prototypes. ANSI C is the
- most portable standard today and we don't write this only for the
- Amiga. Always keep in mind that the source you write should compile
- on PC and UNIX also.
-
- Some parts of the OS can't be written in C since C lacks knowledge
- about the CPU (eg. interrupts and exceptions). This code is CPU
- dependant and there is no way to circumvent this. For such code,
- assembler has to be used. Upto now, no assembler has been chosen.
- GAS is a hot candidate since it is available for all systems but
- many Amiga users (and especially the hardware hackers) don't know
- it and therefore we might choose something that is more "native" to
- the Amiga. Don't expect it to be SAS/C's assembler or any other
- commercial one, since not everyone can access it. If we choose an
- assembler, it will be a public domain one so anyone can access it.
-
- * The "General Amiga Development Guidelines" apply (see AMIGA ROM
- Kernal Reference Manual (RKRM): Libraries, third edition, page
- 13, "Introduction to Amiga System Libraries").
-
- Note: These Guidelines mostly contain "How to code well"-tips
- and some Amiga-specific things, like how to wait for a signal.
- Due to lack of time and copyright-issues, I did not sit down
- and copy it.
-
- * The language for all files is ENGLISH until further notice how
- the format of a multi-lingual file is.
-
- * The author of a file has to include his email for fast resonse
- in case of bugs and problems.
-
- * Compatability is an issue. If you can, try to compile the code
- on as many different platforms and/or compilers as you can.
- Don't use Amiga-specific constructs like #pragma or __autoexit
- or the like since they are not portable.
-
- * Make your code reentrant (ie. avoid global variables). If you
- really can't, put all globals into a structure and allocate
- it like this:
-
- Wrong:
- int I;
- int Should;
- struct Not Do;
- char This[256];
-
- int main (...)
- {
- ...
-
- I = 1;
-
- ...
- } /* main */
-
- Good:
-
- struct GlobalVars
- {
- int gv_I;
- int gv_Should;
- struct Not gv_Do;
- char gv_This[256];
- } * global; /* This is the _only_ global variable */
-
- #define I global->gv_I
- #define Should global->gv_Should
- #define This global->gv_This
-
- int main (...)
- {
- ...
-
- global = AllocMem (sizeof (GlobalVars), MEMF_CLEAR);
-
- I = 1;
-
- ...
- } /* main */
-
- This might look unneccessary, but it prevents a couple of
- problems:
-
- * Some machines support different amounts of global
- memory. Some allow 64K max, others infinite amounts,
- some have problems with global vars > 32K, others don't.
- * Programs that use global variables can't be made resident.
- * Programmer that use global variables tend to loose control
- about their variables and where they are used and changed.
-
- 1.2 AROS Shared Libraries
- -------------------------
- 1.2.1 AROS Parts
- ----------------
-
- * Put all files for a certain topic in a new directory
- * Every file implements exactly one function (this is due to
- the fact that we might need link-libs for some machines).
- Take a look at the advantage: Compilation is blinding fast :)
- * The file has the same name as the function it contains. For now,
- don't care about 8-digit-max filenames. All letters are lower-case.
- * If a file needs or offers special structures which it wants
- to share with others, but those into an include-file with the
- same name but extension "h" in the same directory.
- * Files which should be offered to the outside (eg. header-files)
- go into a special public-directory.
-
- Since this looks a bit complicated, here is an example. All files and
- directories go below "AOS:":
-
- AOS:
- source/
- exec/
- diagnostics/
- alert.c
- docs/
- public/
- exec/
- exec.doc
- internal/
- lists/
- obj/
- addhead.o addtail.o enqueue.o findname.o insert.o
- remhead.o remove.o remtail.o test.o
- obj_debug/
- addhead.o addtail.o enqueue.o findname.o insert.o
- remhead.o remove.o remtail.o test.o
- public/
- examples/
- exec/
- lists lists.c lists.info lists.lnk lists.o
- smakefile
- include/
- exec/
- lists.h nodes.h
- src/
- addhead.c addtail.c enqueue.c findname.c insert.c
- remhead.c remove.c remtail.c
- tests/
- Makefile test test.c test.info test.lnk test.o
- Makefile
- Makefile
- Makefile
- mail/
- Amigos_Mailinglist
- public/
- examples/
- exec/
- lists lists.c lists.info lists.lnk lists.o smakefile
- include/
- aos/
- amiga.h system.h
- exec/
- lists.h nodes.h
- lib/
- exec.lib
- libs/
- exec.library
- Makefile
-
- Note: The files in the directories are put behind each other to save space.
- Otherwise this list whould extend over 4 pages...
-
- The AOS:-directory contains "source/", "mail/" and "public/". The directories
- "source/" and "mail/" are for developers only. The result of the developing
- step goes to "public/". Everything below this directory is exported in the
- user-archive when we release something.
-
- The "mail/"-directory is developer-specific. It contains mails and
- bug-reports and the like.
-
- The most interesting part is the dir "source/exec/". It contains the
- following sub-dirs: "diagnostics/", "docs/", "internal/" and "lists/". The
- directories "docs/" and "internal/" are mandatory for each part of AOS. The
- former contains the docs for this part of AOS (exec), the latter contains
- all internal stuff (ie. routines and knowledge which is not neccessary to
- use this part, only to implement and develop it).
-
- The other two dirs "diagnostics/" and "lists/" contain two parts of EXEC.
- The former contains diagnostic routines like Alert(), the other everything
- that is linked to EXEC-lists (eg. AddHead()). The "lists/"-dir is quite
- well developed, so we focus on it. The dir itself contains several other
- dirs and a couple of files.
-
- The dirs "obj/" and "obj_debug/" contain compiled object-files. The files
- in the former directory are used for the releases, the files in the latter
- one contain object-files with debugging-information used during developing
- and testing this part. Everything contained in the "public/"-dir is copied
- to "AOS:public/" when a release is generated.
-
- Most files in the "lists/"-dir contain functions for Exec-Lists, but some
- don't. The file "Makefile" contains the rules to compile all files (all),
- to compile all files with debug-options (debug), to compile the test
- (test), to compile a debug-version of the test (debug_test), to clean the
- directory and all sub-dirs (clean) and to make a distribution (dist; this
- mainly copies all files into "AOS:public/").
-
- The directory "tests/" contains a Makefile and a test-program to test all
- features of this part. Creating and running the test should allow to check
- every aspect of this part in a automatic way (ie. in the end a great "make
- test" in the main-dir should yield a YES/NO-answer to "Does everything work
- ?" and a more specific answer to "If something doesn't work, what is wrong
- ?").
-
- 1.2.2 AOS Parts Makefile
- ------------------------
-
- The Makefile defines the following rules:
-
- all - Create all files that have changed anew with default options.
- Object-files are places below "obj/".
- debug - Like all, but the files are compiled with debug-options
- and all object-files are put below "obj_debug/".
- test - Create a program called "test" which tests every feature
- of this part. Larger tests are done elsewhere. The test
- should return the information that no errors occurred
- ("No Errors") or a hint what went wrong. Other output
- is optional.
- debug_test - This rule should create test, too, but this time
- all available debug-information should be included. Test
- is to be linked with the object-files from "obj_debug/".
- clean - This rule cleans the directory and all sub-dirs, too.
- Cleaning means "remove any file that has been created
- by the Makefile".
- dist - Make a distribution. This mainly means to copy public
- files in the appropriate places. If you do this in the
- main directory, the Makefile will also create a couple
- of archives with all sources and all binaries.
-
- 1.2.3 Looking Into Files: C-Headers
- -----------------------------------
-
- This is a sample header-file:
-
- ------------------------------ cut --------------------------------------------
- #ifndef EXEC_LISTS_H
- #define EXEC_LISTS_H
- --------------- to be continued... --------------------------------------------
-
- This has to be here in every include-header ! It is meant to prevent
- hassle for the user of the file. This way, the user (and we) can include
- this file as often has he wants or has to (through other include-headers).
- The name of the define can always be derived by converting all characters
- to upper case and replacing all non-characters by "_". The name of the
- file is "exec/lists.h", therefore the define is "EXEC_LISTS_H".
-
- This is the first thing in the header file since some C preprocessors
- check this line and omit the whole file if the symbol is defined already.
-
- --------------------- continue ------------------------------------------------
- /******************************************************************************
-
- FILE
- $VER: exec/lists.h 1.0 (26.8.95)
-
- DESCRIPTION
- Prototypes and macros for exec-lists.
-
- ******************************************************************************/
- --------------- to be continued... --------------------------------------------
-
- This the header for exec-lists. It contains the two entries FILE and
- DESCRIPTION. After FILE follows the version-information. The first
- entry of the version information is the name of the file. Since
- include-files are grouped by the part they belong to, the full
- name is "exec/lists.h". Then comes the version itself (1.0). The first
- figure gives the version, the latter the revision. The version is
- incremented, when something important has been done (eg. a release,
- a things have been renamed, something has been done which might
- break old software, etc.). The revision is incremented every time
- something small has been done (bug-fix, etc.) or when the version is
- not changed :)
-
- --------------------- continue ------------------------------------------------
- /**************************************
- Includes
- **************************************/
- #ifndef AOS_SYSTEM_H
- # include <aos/system.h>
- #endif
- #ifndef EXEC_NODES_H
- # include <exec/nodes.h>
- #endif
- --------------- to be continued... --------------------------------------------
-
- The first thing in a include-header is the inclusion of all files that are
- neccessary to compile it WITHOUT including ANYTHING else before ! If you
- don't see the reason for this, just think of a first-time user who tries to
- use a feature of AOS. He includes the header-file for this feature and gets
- "error in line 15.". What will he think ? "Aren't these ^/§&% able to write
- correct header-files ???" or "What the hell does this (/§"&%$ include-file
- need to compile ?". He doesn't know, but the author of the file does and so
- the author does what belongs to him :)
-
- --------------------- continue ------------------------------------------------
- /**************************************
- Structures
- **************************************/
- --------------- to be continued... --------------------------------------------
-
- Notices these nice headers ? They are used to give the file structure :)
-
- --------------------- continue ------------------------------------------------
- /* Normal list */
- struct List
- {
- struct Node * lh_Head,
- * lh_Tail,
- * lh_TailPred;
- UBYTE lh_Type;
- BYTE l_pad;
- };
- --------------- to be continued... --------------------------------------------
-
- Every structure gets it's own short comment. Try to format them if possible;
- here, we put all types, all pointers and all names above each other. If the
- structure is complicated, don't hesitate to make large comments before
- the structure or behind each field. Make sure though, to put them below
- each other for improved readability.
-
- --------------------- continue ------------------------------------------------
-
- /* Minimal list */
- struct MinList
- {
- struct Node * lh_Head,
- * lh_Tail,
- * lh_TailPred;
- };
-
-
- /**************************************
- Makros
- **************************************/
- --------------- to be continued... --------------------------------------------
-
- Another header; now we define all macros for this functions.
-
- --------------------- continue ------------------------------------------------
- #undef __CAST
- #ifdef AOS_ALMOST_COMPATIBLE
- # define CAST(x,y) ((x)y)
- #else
- # define CAST(x,y) (y)
- #endif
- --------------- to be continued... --------------------------------------------
-
- Throughout the files, the AOS_ALMOST_COMPATIBLE-define is used to
- mask lines which implement features or enhancements that are not
- 100% compatible to the original OS but will probably not break
- old software. For a better example, see below.
-
- --------------------- continue ------------------------------------------------
- #define IsListEmpty(l) \
- ( (CAST(struct List *,l)->lh_TailPred) == (struct Node *)(l) )
-
- #define IsMsgPortEmpty(mp) \
- ( (CAST(struct MsgPort *,mp)->mp_MsgList.lh_TailPred) \
- == (struct Node *)(&(CAST(struct MsgPort *, mp)->mp_MsgList)) )
- --------------- to be continued... --------------------------------------------
-
- These two macros are (almost) original. The difference is that the
- AOS-version allows to use anything as parameter of the macros. The
- original version whould just work with real lists or casts to lists.
-
- --------------------- continue ------------------------------------------------
- #ifdef AOS_ALMOST_COMPATIBLE
- # define NewList(l) (CAST(struct List *,l)->lh_TailPred \
- = (struct Node *)(l), \
- CAST(struct List *,l)->lh_Tail = 0, \
- CAST(struct List *,l)->lh_Head \
- = (struct Node *)\
- &(CAST(struct List *,l)->lh_Tail))
- --------------- to be continued... --------------------------------------------
-
- And now something which can't be find in the original sources. Here
- comes a couple of macros which whould be quite useful in the OS,
- but which are missing.
-
- --------------------- continue ------------------------------------------------
- # define GetHead(l) (CAST(struct List *,l)->lh_Head->ln_Succ \
- ? CAST(struct List *,l)->lh_Head \
- : (struct Node *)0)
- # define GetTail(l) (CAST(struct List *,l)->lh_TailPred->ln_Succ \
- ? CAST(struct List *,l)->lh_TailPred \
- : (struct Node *)0)
- # define GetSucc(n) (CAST(struct Node *,n)->ln_Succ->ln_Succ \
- ? CAST(struct Node *,n)->ln_Succ \
- : (struct Node *)0)
- # define GetPred(n) (CAST(struct Node *,n)->ln_Pred->ln_Pred \
- ? CAST(struct Node *,n)->ln_Pred \
- : (struct Node *)0)
- #endif /* AOS_ALMOST_COMPATIBLE */
-
- /******************************************************************************
- ***** ENDE exec/lists.h
- ******************************************************************************/
-
- #endif /* EXEC_LISTS_H */
- ------------------------------ cut --------------------------------------------
-
- This is the end of the file. After the "#endif" follows the comment
- with the name of the define above. This has to be used for every "#endif"
- that is "far away" of the corresponding "#if" (ie. more than about 20
- lines).
-
- 2. Other Files
-
- Throughout the directories files with the name "TODO". They contain
- information about the state of a project or part or whatever. The TODO-file
- contains a list of what has to be done, yet. The list looks like this:
-
- ------------------------------ cut --------------------------------------------
- * Write the functions for exec-lists
- + Write good docs for exec-lists
- o Write exec-ports
- o AddPort()
- o FindPort()
- o etc.
-
- BUGS:
- o digulla@home.lake.de metioned that not all functions have good
- comments. (NTH)
-
- o the function Alert() doesn't show that nice red frame around the
- message.
- ------------------------------ cut --------------------------------------------
-
- ie. every entry in introduced with a "o". If an entry extends over several
- lines, then the second and all folowing lines are indented.
-
- If an entry is in work, the "o" changes to "+". When it is done, change the
- "+" to "*". If you want to keep records on how long you worked on it, add
- the time in hours in "()" after the entry. (eg. "(8h)").
-
- Also in this file is a section which is introduced by "BUGS:". In this
- section, all bugs, reports, etc. are collected.
-
- !!! TREAT THIS PART AS READ-ONLY !!!
-
- This way the file might get quite long, but that way it is easy to check if
- a bug has already gone or not or if someone is working on it. After the
- entry, some information follows in "()". It is a comma-separeted list of
- these abbreviations:
-
- NTH: Nice To Have. Great if someone finds the time to do it,
- but it doesn't really hurt.
- TODO: This one was missing in the original TODO. I have to
- do it some time.
- BUG: This is a bug but it doesn't need immediate fixing.
- SEV: A severe bug ! This means that it really hurts and it
- needs immediate work.
- #h: # is the number of hours it took to fix the problem (optional)
- FIX name: Name is the name of the person who fixed the bug.
-
- 3. The Source Style
- -------------------
-
- The information in the next chapters is divided into "Must Have" and
- "Nice To Have". "Must Have" means that source which doesn't comply
- to this will be rejected. "Nice To Have" means "If you follow these
- rules, the code will look nicer and others will understand it
- better" but if you object to these rules, all that will happen is
- a deep sigh from me :-)
-
- 3.1 The Style "Must Have"
- -------------------------
-
- The rules in this chapter are neccessary to compile the source with
- different compilers on different systems. If you don't follow these
- rules, you make your life easier but more difficult for many others.
- So think about it lazy lad...
-
- 3.1.1 Includes
- --------------
-
- AROS offers a layer of includes to adopt to the special needs of a
- certain compiler and/or hardware. All these includes can be found
- in the "aros" directory in the AROS includes. The meaning of these
- includes are described in source/aros/docs. These includes contain
- a great amount of knowledge about systems and hardwares. They
- define certain hardware independant macros to make your life
- easier and they define flags for you to check to see whether a
- certain feature is requested/neccessary/possible or not.
-
- 3.1.2 Arguments in Registers
- ----------------------------
-
- On the Amiga, it is tradition to call OS functions with the arguments
- in CPU registers, on other systems this is not; either because the
- CPU has not the same registers, either because the compiler doesn't
- allow for specifying a certain register for a certain parameter.
- To avoid breaking code for the Amiga and to avoid that we need two
- types of source, some very sophisticated macros have been designed to
- work around this problem.
-
- First, if you need a register and your compiler says "to link a
- parameter with a register use this syntax", DON'T use this. Instead,
- name registers as "A0", "D3" etc. These are in fact macros which
- are expanded into something your compiler can understand. This is
- done automatically; all you have to do is to include <aros/libcall.h>.
-
- See source/aros/docs/libcall.doc for a description how to do it.
- Most of the time, you need not worry, since the headers for all
- library functions are generated with a script and you need only
- fill in the source for the function.
-
- 3.1.3 Autodocs and AROS
- -----------------------
-
- AROS doesn't use the Autodoc standard for OS functions because
- Autodocs are too limited for this. Our format, however, can be
- converted into Autodocs with little effort.
-
- Here is an example for a complete header:
-
- --------- header of source/exec/kernel/src/rawdofmt.c ------------------------
- /*
- $Id$
- $Log$
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- These are for RCS. $Id$ is replaced by the version, the name of the
- file and the person that changed it the last time. $Log$ is replaced
- by a list of all changed made to the file with date and name of the
- person that did it.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- Desc:
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- Here comes the short description. With Autodocs, this would have been in
- the NAME section. NOTE: This part of the header is subject to change. If it
- is changed all sources are converted automatically.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- Lang: english
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- The language of the header. This is for future expansion so we can offer
- Autodocs in different languages. NOTE: This part of the header is subject
- to change. If it is changed all sources are converted automatically.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- */
- #include "exec_intern.h"
- #include "machine.h"
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- Here is a list of internal includes, ie. includes that are neccessary to
- compile this file but NOT to use the function !
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- /*****************************************************************************
-
- NAME */
- #include <exec/types.h>
- #include <clib/exec_protos.h>
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- This is the header of the file. Since every file contains only a single
- function, there is no special file-header but only the header of the
- function. By making use of C-comments, we mix source-code and documentation
- in a way which makes it unneccessary to write code twice. This also helps
- in writing working code since the documentation is always up-to-date.
-
- The first thing are the include-files the user of this function needs. Any
- internal includes would go in front of the first line. For this function,
- we need the header-file for lists and the prototypes for exec-functions.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- __AROS_LH4I(APTR, RawDoFmt,
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- Here we use a macro to make the prototype usable for other compilers on
- other systems. For a complete description of the __AROS_LH-macros, look
- into source/aros/docs/libcall.doc. Here the macro declares a function that
- is named "RawDoFmt", returns APTR, has 4 arguments and doesn't need the
- libbase (see below).
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- /* SYNOPSIS */
- __AROS_LA(UBYTE *, formatString, A0),
- __AROS_LA(APTR , dataStream, A1),
- __AROS_LA(VOID_FUNC, putChProc, A2),
- __AROS_LA(APTR , putChData, A3),
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- These are all arguments. Note the use of the C comment. This way, the
- arguments have to be specified only once! No need to worry if the types and
- names in the header really match the ones used in the part of the file that
- the compiler actually sees.
-
- Every argument is encapsulated in a __AROS_LA-macro which sorts the order
- of arguments (some compilers need the register after the type and the
- like). We specify the type, the name and the CPU register in which the
- argument is passed. The CPU register is safely ignored if it can't be used
- (eg. because the CPU has no such register or the compiler doesn't allow to
- specify in which register a parameter has to be passed in a.s.o.).
-
- The parameter putChProc is declared as type "VOID_FUNC" due to the fact
- that the use of the macro makes it impossible to declare it as
- "void(*putChProc)()". There are more of these types in
- include/aros/libcall.h.
-
- Note that the types, stars and parameter-names are put below each other to
- increase readability.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- /* LOCATION */
- struct ExecBase *, SysBase, 87, Exec)
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- These are the last four parameters of all __AROS_LH-macros. They
- declare the type and name of the libbase, the LVO offset of the function
- and the name of the library for this function (in this order). The
- first two arguments are ignored if LVOs are not used for this system.
- The LVO itself is always ignored, but it has to be somewhere and there
- was no much better place for it. The last argument is used to put a
- common prefix before all functions of a library so there are no problems
- with linking the library to code that needs stubs to call library
- functions (same names for functions and the like).
-
- There are other flavours of __AROS_LH-macros which allow to declare
- a function (prototype in a include file) and to call it (using LVOs
- if neccessary).
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- /* FUNCTION
- printf-style formatting function with callback hook.
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- Now we give a complete description of what the function does. This includes
- all features and usages but excludes return-values and parameters if not
- absolutely neccessary.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- INPUTS
- FormatString - Pointer to the format string with any of the following
- stream formatting options allowed:
-
- %[leftalign][minwidth.][maxwidth][size][type]
-
- leftalign - '-' means align left. Default: align right.
- minwidth - minimum width of field. Defaults to 0.
- maxwidth - maximum width of field (for strings only).
- Defaults to no limit.
- size - 'l' means longword. Defaults to word.
- type - 'b' BCPL string. A BPTR to a one byte
- byte count followed by the characters.
- 'c' single character.
- 'd' signed decimal number.
- 's' C string. NUL terminated.
- 'u' unsigned decimal number.
- 'x' unsigned sedecimal number.
-
- dataStream - Array of the data items.
- putChProc - Callback function. Called for each character, including
- the NUL terminator.
- putChData - Data propagated to each call of the callback hook.
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- Here are the parameters. Don't name the type; the name is enough. The
- parameter is separated from the rest of the description by a "-" (minus).
- The description is indented, if it doesn't fit in a single line. If you
- want to group parameters, put them into a comma-separated list. If this
- list extends over more than one line, it is NOT indented. It is allowed to
- put each parameter in such a list in his own line. The last parameter in
- the list is not followed by a comma (just in case...).
-
- The description should contain every bit of information to understand what
- this parameter does. If a parameter is a return value (ie. the functions
- puts something in it and ignores the old value), you can omit it here and
- explain it in the next section. If the function modifies the parameter, you
- should explain it here (at least the part of the explanation which tells
- with which values in this parameter the function can be called).
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- RESULT
- Pointer to the rest of the dataStream.
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- Here we explain what the function returns or what it changes. For example
- the RESULT of Supervisor() is that we are in supervisor mode now.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- NOTES
- The field size defaults to words which may be different from the
- default integer size of the compiler.
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- Mention all aspects of the function that the user of it should look out for
- (eg. unexpected results, problems, special circumstances, if the function
- breaks on NULL-parameters or if it doesn't).
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- EXAMPLE
- // build a sprintf style function
-
- static void callback (UBYTE chr, UBYTE **data)
- {
- *(*data)++ = chr;
- }
-
- void my_sprintf (UBYTE *buffer, UBYTE *format, ...)
- {
- RawDoFmt (format, &format+1, callback, &buffer);
- }
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- This section should contain a most complete example of how to use
- the function. Since one cannot use normal C-Style comments here,
- there are a couple of ways to circumvent this:
-
- a) Use "EXAMPLE */" instead of "EXAMPLE" and put the whole
- example in a "#ifdef COMPILE_EXAMPLE"..."#endif" block.
- b) Use C++-style comments "// This is a comment."
- c) Use Autodoc-Style C comments: "\* This is a comment *\"
-
- All these ways are accepted by the Autodoc compiler.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- BUGS
- PutChData cannot be modified from the callback hook.
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- Now here for the interesting part: Things that should but don't work.
- If you can, name a workaround.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- SEE ALSO
- printf(), sprintf(), vsprintf(), fprintf()
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- Specify function here, which work on the same data (eg. OpenWindow()
- should mention all other functions working on windows). Always remember:
- Too much information is less frustrating than not enough information.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- INTERNALS
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- This section is for experts only. For the mortal user, it is omitted.
- Name things here someone who tries to understand your code should know.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- HISTORY
- 22-10-95 created by m. fleischer
- ----- header of source/exec/kernel/src/rawdofmt.c (to be continued) ----------
-
- This part is subject of change, too, since RCS is doing it already. Maybe
- only major changes will be mentioned here.
-
- -------- header of source/exec/kernel/src/rawdofmt.c (continued) -------------
- ******************************************************************************/
- ----------- header of source/exec/kernel/src/rawdofmt.c (end) ----------------
-
- The terminator of the header. The AROS-Header-To-Autodoc converter stops
- here. The rest of the file is ignored.
-
- 3.2 The Style "Nice To Have"
- ----------------------------
-
- Now I explain my favourite style to code. Since I like structured code,
- I insert quite a lot of space in my code. The result looks good but
- on the other hand you need a lot of resolution on you screen to see
- more than a small portion of my code.
-
- 3.2.1 Indent
- ------------
-
- One indent level is 4 spaces. Two levels of indentation are sometimes
- a tab. Tabs are is alway set every 8 spaces.
-
- 3.2.2 Comments
- --------------
-
- Comments are aligned with the rest of the source:
-
- if (...)
- {
- }
-
- /* This is a comment */
- a = 1;
-
- No space follows a comment, but at least one emtpy line goes before it.
- If a comment is long, it looks like this:
-
- a = 0;
-
- /*
- This
- is a
- very
- long
- comment (somehow).
- */
- a = 1;
-
- I don't use the "*-before-every-line" since that results in code where the
- comments don't reflect the recent changes since that would mean to remore
- all *'s, change the comment and the reinsert the *'s again.
-
- 3.2.2 Blocks
- ------------
-
- Blocks look like this:
-
- int foo (int a)
- {
- if (...)
- {
- while (...)
- {
- }
- } /* ... */
- } /* foo */
-
- The braces are above each other and the text in a block is
- indented once. Note the use of comments here. Functions always get
- an end-comment with the name of the function. Blocks get a
- short description of the header of the block if the first and
- the last line are about 20 lines away.
-
- 3.2.3 Spaces
- ------------
-
- I insert a space...
-
- - after a variable, function or C keyword
- - before and after operators
-
- Sometimes a insert more than one space to get this:
-
-
- struct RastPort * rp;
- int count;
-
- some->struct = 0;
- some->even.more.complicated.struct = 1;
- count = 0;
-
- ie. a tabular look.
-
- Empty lines are inserted whenever the semantic changes:
-
- if (a)
- {
- } /* a != 0 */
- if (b)
- {
- } /* b != 0 */
-
- a = 1;
-
- call (a, function);
- call (another, function);
-
- ...
-
- ie. the two if()'s aren't separated, then an empty line and an assignment,
- an empty line and a couple of function calls.
-
- 3.2.4 Breaking Long Expressions
- -------------------------------
-
- Long expressions look like this:
-
- if (maybe
- || sure
- || (a
- && this_is_never_true (but,
- who, knows)
- && TRUE
- )
- )
-
- This looks unfamiliar, but it shows at a glance what part of the expression
- belongs to which other part and how the sub-expressions are connected.
-
- These are the rules:
-
- a) Each part of the expressions get's it's ownline except it is
- the first part.
- b) An operator or a "(" are the first things in a line. If there
- are both, the operator comes first.
- c) If a subexpression (eg. a function call) is too long, it is
- split at a space and indented two times (to avoid visual
- conflicts with subexpressions at a lower level).
-
- Advantages:
- - Most parts of the expression can be inserted or removed with line operations
- (ie. delete whole line or insert a new line).
- - No need to reformat the whole expression if you inserted or deleted
- a lot.
- - Parenthese levels are easy distinguishable.
-